package com.wsgalaxy.anmanager;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.provider.ContactsContract;
import android.util.Base64;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.Runnable;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by wssxk on 9/25/17.
 */

public class SocketProcess implements Runnable {

    Socket socket;
    MainService.ProcessHandler ms_handler;
    JSONObject _request = null;
    Context ms_content = null;

    SimpleDateFormat date_format = new SimpleDateFormat("HH:mm:ss");

    SocketProcess(Socket s, MainService.ProcessHandler handler, Context content) {
        socket = s;
        ms_handler = handler;
        ms_content = content;
    }

    @Override
    public void run() {
        byte buf[] = new byte[4096];
        String json_str;
        try {
            InputStream is = socket.getInputStream();
            int read_size = -1;
            read_size = is.read(buf);
            if (read_size == -1) {
                closeSocket();
                throw new Exception();
            }

            json_str = new String(buf, 0, read_size, "UTF-8");
            _request = new JSONObject(json_str);
            //_request = request;
            requestProcess();

        } catch (Exception e) {
            Log.d("wssxk", "readError");
            closeSocket();
        }
    }


    public void requestProcess() {
        Log.d("wssxk", "request: " + _request.toString());

        try {
            log_show("request: \n" + _request.toString(4));
            String name = _request.getString("name");
            if (name.equals("devices_info")) {
                _devices_info();
            } else if (name.equals("check_connect")) {
                _check_connect();
            } else if (name.equals("app_list")) {
                _app_list();
            } else if (name.equals("app_backup")) {
                _app_backup();
            } else if (name.equals("file_list")) {
                _file_list();
            } else if (name.equals("contacts_backup")) {
                _contacts_backup();
            } else if (name.equals("contacts_recovery")) {
                _contacts_recovery();
            } else {
                throw new Exception();
            }
        } catch (Exception e) {
            closeSocket();
        }



        /*
        try {
            OutputStream output_stream = socket.getOutputStream();
            JSONObject res = new JSONObject();
            res.put("name", "android_response中文");
            res.put("status", "response");
            output_stream.write(res.toString().getBytes());

        } catch (Exception e) {
            Log.i("wssxk", "read error");
        }

        */

    }

    public void closeSocket()
    {
        try {
            socket.close();
        } catch (Exception e) {}

    }


    void _devices_info() {
        //Build.DISPLAY


        try {

            JSONObject resp = new JSONObject();
            resp.put(AnGlobal.NAME, _request.getString(AnGlobal.NAME));
            resp.put(AnGlobal.STATUS, AnGlobal.RESPONSE);

            JSONObject data = new JSONObject();
            data.put(AnGlobal.RESULT, 1);
            data.put("board", Build.BOARD);
            data.put("brand", Build.BRAND);
            data.put("device", Build.DEVICE);
            data.put("manufacturer", Build.MANUFACTURER);
            data.put("model", Build.MODEL);
            data.put("product", Build.PRODUCT);
            data.put("SDK", Build.VERSION.SDK_INT);
            data.put("android_version", Build.VERSION.RELEASE);
            data.put("kernel", System.getProperty("os.name") + " " + System.getProperty("os.version"));
            data.put("arch", System.getProperty("os.arch"));

            resp.put(AnGlobal.DATA, data);

            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(resp.toString().getBytes());

            log_show("response: \n" + resp.toString(4));
            closeSocket();
        } catch (Exception e) {}

    }

    //useless
    void _connect_check() {
        try {
            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(_request.toString().getBytes());
            
            log_show("response: \n" + _request.toString(4));
            closeSocket();
        } catch (Exception e) {
            closeSocket();
        }
    }

    void _check_connect() {
        try {
            OutputStream socket_op = socket.getOutputStream();
            InputStream socket_ip = socket.getInputStream();
            byte[] buf = new byte[1024];
            while (true) {
                socket_op.write(_request.toString().getBytes());
                if (socket_ip.read(buf) == -1) {
                    break;
                }
            }
            closeSocket();

            //socket_op.write(_request.toString().getBytes());

            //log_show("response: \n" + _request.toString(4));
            //closeSocket();
        } catch (Exception e) {
            closeSocket();
        }
    }

    void _app_list() {
        PackageManager pm = ms_content.getPackageManager();
        List<PackageInfo> pkgs = pm.getInstalledPackages(0);
        SimpleDateFormat app_date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm");

        try {
            JSONObject resp = new JSONObject();
            resp.put(AnGlobal.NAME, "app_list");
            resp.put(AnGlobal.STATUS, AnGlobal.RESPONSE);
            JSONObject data = new JSONObject();
            JSONArray user = new JSONArray();
            JSONArray system = new JSONArray();

            JSONObject each_app = null;
            //ByteArrayOutputStream byte_array_ops = new ByteArrayOutputStream();

            for (int t = 0; t < pkgs.size(); t ++) {
                PackageInfo pkginfo = pkgs.get(t);
                each_app = new JSONObject();
                //byte_array_ops.reset();

                each_app.put("label", pkginfo.applicationInfo.loadLabel(pm).toString());
                each_app.put("package_name", pkginfo.packageName);
                each_app.put("version", pkginfo.versionName);
                each_app.put("install_date", app_date_format.format(new Date(pkginfo.lastUpdateTime)));

                /*
                Drawable icon = pkginfo.applicationInfo.loadIcon(pm);
                Bitmap icon_bm = ((BitmapDrawable) icon).getBitmap();
                icon_bm.compress(Bitmap.CompressFormat.PNG, 100, byte_array_ops);
                byte[] png_data = byte_array_ops.toByteArray();
                each_app.put("icon", Base64.encodeToString(png_data, Base64.DEFAULT));
                */

                if ((pkginfo.applicationInfo.flags & pkginfo.applicationInfo.FLAG_SYSTEM) == 0) {
                    user.put(each_app);
                } else {
                    system.put(each_app);
                }

                each_app = null;
            }

            //data.put(AnGlobal.RESULT, AnGlobal.SUCCEED);
            data.put(AnGlobal.RESULT, 1);
            data.put("user", user);
            data.put("system", system);

            resp.put(AnGlobal.DATA, data);

            log_show("response: \n" + resp.toString(4));

            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(resp.toString().getBytes());

            closeSocket();

        } catch (Exception e) {
            Log.d("wssxk", "error: app_list");
            closeSocket();
        }


    }

    void _app_backup() {}

    void _file_list() {
        try {

            String path_str = _request.getJSONObject(AnGlobal.DATA).getString("path");

            log_show("debug: " + path_str);

            File path = new File(path_str);
            if (!path.exists() || !path.isDirectory() || !path.canRead()) {
                JSONObject error = new JSONObject();
                error.put(AnGlobal.NAME, _request.getString(AnGlobal.NAME));
                error.put(AnGlobal.STATUS, AnGlobal.RESPONSE);
                JSONObject error_data = new JSONObject();
                error_data.put(AnGlobal.RESULT, 0);
                error_data.put(AnGlobal.DATA, error_data);

                log_show("response: \n" + error.toString(4));

                OutputStream socket_op = socket.getOutputStream();
                socket_op.write(error.toString().getBytes());
                return;

            }

            String [] files_name = path.list();

            JSONObject each_file = null;
            JSONArray files_ls = new JSONArray();

            for (int t = 0; t < files_name.length; t ++) {
                each_file = new JSONObject();
                each_file.put("name", files_name[t]);

                String each_path_str = path_str + "/" + files_name[t];
                File each_path = new File(each_path_str);
                if (each_path.isDirectory()) {
                    each_file.put("type", "dir");
                } else {
                    each_file.put("type", "file");
                    each_file.put("size", each_path.length());
                }

                each_file.put("update_date", each_path.lastModified());

                files_ls.put(each_file);

            }

            JSONObject resp = _request;
            JSONObject data = new JSONObject();
            data.put(AnGlobal.RESULT, 1);
            data.put("files", files_ls);
            resp.put(AnGlobal.STATUS, AnGlobal.RESPONSE);
            resp.put(AnGlobal.DATA, data);

            log_show("response: \n" + resp.toString(4));

            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(resp.toString().getBytes());

            closeSocket();

        } catch (Exception e) {
            closeSocket();

        }
    }


    void _contacts_backup()
    {
        try {

            JSONArray contacts_array = new JSONArray();
            JSONObject each_contact = null;
            String name = null;
            String number = null;

            Cursor contacts_cursor = ms_content.getContentResolver()
                    .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

            while (contacts_cursor.moveToNext()) {
                name = contacts_cursor.getString(contacts_cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                number = contacts_cursor.getString(contacts_cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                each_contact = new JSONObject();
                each_contact.put("name", name);
                each_contact.put("number", number);
                contacts_array.put(each_contact);
            }


            JSONObject resp = _request;
            _request.put(AnGlobal.STATUS, AnGlobal.RESPONSE);
            JSONObject resp_data = new JSONObject();
            resp_data.put(AnGlobal.RESULT, 1);
            resp_data.put("contacts", contacts_array);
            resp.put(AnGlobal.DATA, resp_data);


            log_show("response: \n" + resp.toString(4));

            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(resp.toString().getBytes());

            closeSocket();


        } catch (Exception e) {
            closeSocket();
        }

    }


    void _contacts_recovery()
    {

        try {

            JSONArray contacts_array = _request.getJSONObject(AnGlobal.DATA).getJSONArray("contacts");
            JSONObject each_contact = null;
            Uri uri_raw_contacts = Uri.parse("content://com.android.contacts/raw_contacts");
            Uri uri_contacts = Uri.parse("content://com.android.contacts/data");
            ;
            ContentResolver resolver = ms_content.getContentResolver();

            for (int t = 0; t < contacts_array.length(); t++) {
                each_contact = contacts_array.getJSONObject(t);

                ContentValues values = new ContentValues();
                long contactId = ContentUris.parseId(resolver.insert(uri_raw_contacts, values));

                /* 往 data 中添加数据（要根据前面获取的id号） */
                // 添加姓名
                //uri = Uri.parse("content://com.android.contacts/data");
                values.put("raw_contact_id", contactId);
                values.put("mimetype", "vnd.android.cursor.item/name");
                values.put("data2", each_contact.getString("name"));
                resolver.insert(uri_contacts, values);

                // 添加电话
                values.clear();
                values.put("raw_contact_id", contactId);
                values.put("mimetype", "vnd.android.cursor.item/phone_v2");
                values.put("data2", "2");
                values.put("data1", each_contact.getString("number"));
                resolver.insert(uri_contacts, values);
            }

            JSONObject resp = _request;
            JSONObject resp_data = new JSONObject();
            resp.put(AnGlobal.STATUS, AnGlobal.RESPONSE);
            resp_data.put(AnGlobal.RESULT, 1);
            resp.put(AnGlobal.DATA, resp_data);


            OutputStream socket_op = socket.getOutputStream();
            socket_op.write(resp.toString().getBytes());
            log_show("response: \n" + resp.toString(4));

            closeSocket();

        } catch (Exception e) {
            log_show("debug");
            closeSocket();
        }

    }


    void log_show(String log) {
        Message msg = ms_handler.obtainMessage();
        Bundle data = new Bundle();
        data.putCharSequence("json", date_format.format(new Date()) + ">>" + log);
        msg.setData(data);
        ms_handler.sendMessage(msg);
    }



}
